package com.qumitech.visualnovel.component.thirdapi.aliyun;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.springframework.web.multipart.MultipartFile;

import com.qumitech.visualnovel.component.util.GetPropertiesUtils;
import com.qumitech.visualnovel.component.exception.BusinessException;

import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.net.URL;

public class AliYunOSSUtil {
    private static final long SecondsPerHour = 3600;
    //取值范围 15min-1h
    private static final long TokenExpireTime = SecondsPerHour;
    private static final long TokenCacheExpireTime = TokenExpireTime - 60;

    private static final String ALIYUN_OSS_ACCESS_KEY_ID = GetPropertiesUtils.getProperty("common", "aliyun_oss_access_key_id");
    private static final String ALIYUN_OSS_ACCESS_KEY_SECRET = GetPropertiesUtils.getProperty("common", "aliyun_oss_access_key_secret");
    private static final String ALIYUN_OSS_BUCKET = GetPropertiesUtils.getProperty("common", "aliyun_oss_bucket");
    private static final String ALIYUN_OSS_ENDPOINT = GetPropertiesUtils.getProperty("common", "aliyun_oss_endpoint");
    private static final String ALIYUN_OSS_ROLEARN = GetPropertiesUtils.getProperty("common", "aliyun_oss_rolearn");
    private static final String REGION_CN_HANGZHOU = "cn-hangzhou";

    private static LoadingCache<String, Map<String, String>> tokenCache = CacheBuilder.newBuilder()
            .initialCapacity(1)
            .expireAfterWrite(TokenCacheExpireTime, TimeUnit.SECONDS)
            .build(new CacheLoader<String, Map<String, String>>() {
                @Override
                public Map<String, String> load(String key) throws Exception {
                    return getTokenByHttps();
                }
            });

    public static void uploadRemoteFile(String url, String fileKey) {
        OSS ossClient = new OSSClientBuilder().build(ALIYUN_OSS_ENDPOINT, Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_ID), Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_SECRET));
        try {
            InputStream in = new URL(url).openStream();
            PutObjectRequest putObjectRequest = new PutObjectRequest(ALIYUN_OSS_BUCKET, fileKey, in);
            ossClient.putObject(putObjectRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ossClient.shutdown();
    }

    public static void uploadLocateFile(MultipartFile file, String fileKey) {
        OSS ossClient = new OSSClientBuilder().build(ALIYUN_OSS_ENDPOINT, Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_ID), Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_SECRET));
        try {
            InputStream in = file.getInputStream();
            // 上传内容到指定的存储空间（bucketName）并保存为指定的文件名称（fileKey）。
            PutObjectRequest putObjectRequest = new PutObjectRequest(ALIYUN_OSS_BUCKET, fileKey, in);
            ossClient.putObject(putObjectRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ossClient.shutdown();
    }

    public static Map<String, String> getToken(){
        Map<String, String> map = null;
        try{
            map = tokenCache.get(ALIYUN_OSS_BUCKET);
        }catch (ExecutionException e){
            map = getTokenByHttps();
        }
        return map;
    }

    public static Map<String, String> getTokenByHttps() {
        Map<String, String> respMap = new LinkedHashMap<>();
        try {
            String roleSessionName = "miyin-001";
            String policy = "{\n" +
                    "  \"Statement\": [\n" +
                    "    {\n" +
                    "      \"Action\": [\n" +
                    "        \"oss:PutObject\",\n" +
                    "        \"oss:ListParts\",\n" +
                    "        \"oss:AbortMultipartUpload\"\n" +
                    "      ],\n" +
                    "      \"Effect\": \"Allow\",\n" +
                    "      \"Resource\": [\"acs:oss:*:*:" + ALIYUN_OSS_BUCKET + "/*\"]\n" +
                    "    }\n" +
                    "  ],\n" +
                    "  \"Version\": \"1\"\n" +
                    "}";
            ProtocolType protocolType = ProtocolType.HTTPS;

            final AssumeRoleResponse stsResponse = assumeRole(
                    roleSessionName,
                    policy, protocolType);

            respMap.put("StatusCode", "200");
            respMap.put("AccessKeyId", stsResponse.getCredentials().getAccessKeyId());
            respMap.put("AccessKeySecret", stsResponse.getCredentials().getAccessKeySecret());
            respMap.put("SecurityToken", stsResponse.getCredentials().getSecurityToken());
            respMap.put("Expiration", stsResponse.getCredentials().getExpiration());

        } catch (ClientException e) {
            respMap.put("StatusCode", "500");
            respMap.put("ErrorCode", e.getErrCode());
            respMap.put("ErrorMessage", e.getErrMsg());
        }
        return respMap;
    }

    private static AssumeRoleResponse assumeRole(String roleSessionName, String policy, ProtocolType protocolType) throws ClientException {
        // 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
        IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, AliYunOSSUtil.ALIYUN_OSS_ACCESS_KEY_ID, AliYunOSSUtil.ALIYUN_OSS_ACCESS_KEY_SECRET);
        DefaultAcsClient client = new DefaultAcsClient(profile);

        // 创建一个 AssumeRoleRequest 并设置请求参数
        final AssumeRoleRequest request = new AssumeRoleRequest();
        request.setVersion("2015-04-01");
        request.setMethod(MethodType.POST);
        request.setProtocol(protocolType);

        request.setRoleArn(AliYunOSSUtil.ALIYUN_OSS_ROLEARN);
        request.setRoleSessionName(roleSessionName);
        request.setPolicy(policy);
        request.setDurationSeconds(TokenExpireTime);
        // 发起请求，并得到response
        return client.getAcsResponse(request);
    }

    public static void deleteObject(String key){
        // OSS ossClient = new OSSClientBuilder().build(ALIYUN_OSS_ENDPOINT, Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_ID), Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_SECRET));
        // ossClient.deleteObject(UploadConfig.pictureBucket, key);
    }

    public static void deleteObjectList(List<String> keyList){
        // OSS ossClient = new OSSClientBuilder().build(ALIYUN_OSS_ENDPOINT, Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_ID), Objects.requireNonNull(ALIYUN_OSS_ACCESS_KEY_SECRET));
        // DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(UploadConfig.pictureBucket).withKeys(keyList));
        // List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        // ossClient.shutdown();
    }
}
